#include "gtest/gtest.h"
#include "FileStream.h"

#include <thread>
#include <chrono>


using namespace streamdb;

TEST(FileStreamTest, use){
    auto ss = std::make_shared<FileStream>("stream.db");
    if(ss != nullptr){
        std::cout << "OK" << std::endl;
    }

    ASSERT_TRUE(ss->open().isOk());

    std::string bin;
    ASSERT_TRUE(ss->append(bin).isOk());
    ASSERT_TRUE(ss->append(bin).isOk());
    ASSERT_TRUE(ss->append(bin).isOk());
    ASSERT_TRUE(ss->append(bin).isOk());
    ASSERT_TRUE(ss->append(bin).isOk());

    ASSERT_TRUE(ss->append("1:abc").isOk());
    ASSERT_TRUE(ss->append("2|bcd").isOk());
    ASSERT_TRUE(ss->append("3|efg").isOk());

    int offset = 0;
    {
        auto iter = ss->advance(offset);
        if(iter != nullptr){
            while(iter->hasNext()){
                std::string & text = iter->next();
                ASSERT_TRUE(!text.empty());
                //std::cout << "iterator:" << text << std::endl;
            }
        }
    }
    {
        offset += 2+5;
        auto iter = ss->advance(offset);
        if(iter != nullptr){
            while(iter->hasNext()){
                auto & v = iter->next();
                ASSERT_TRUE(!v.empty());
                //std::cout << "iterator from offset(" << offset << ")/" << ss->getSize() << ":" << v << std::endl;
            }
        }
    }
}


TEST(FileStreamTest, multiThead){
    //thread1
    std::thread th1( [](){
        auto ss = std::make_shared<FileStream>("multiThead.db");
        ASSERT_TRUE(ss != nullptr);
        ASSERT_TRUE(ss->open().isOk());

        for(int i = 0;  i < 10; ++i){
            ss->append("3|efg");
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
        }
    });

    std::thread th2 ( [](){
        for(int i = 0;  i < 10;  ++i){
            auto ss = std::make_shared<FileStream>("multiThead.db");
            ASSERT_TRUE(ss->open().isOk());

            auto iter = ss->begin();
            if(iter != nullptr){
                while(iter->hasNext()){
                    auto & v = iter->next();
                    ASSERT_TRUE(!v.empty());
                    //std::cout << "thread 2 visit:" << v << std::endl;
                }
            }
        }
    });

    th2.join();
    th1.join();
}
